#pragma once 
#include <stddef.h>
#include <assert.h>
namespace CorrectionIndexModule
{
    static const size_t MAXMEMORYSIZE = 256 * 1024;     //最大内存
    static const size_t PAGESIZESHIFT = 13;                      //页的大小为8*1024，这里仅用2的幂次表示
    static const size_t MAXBUCKETNUM = 208;                  //桶的个数
    static const size_t MAXPAGESIZE = 129;                       //页的最大个数 128

    //修正指数类
    class CorrectionIndex
    {
    public:
        //对齐数
        static size_t AlignedNum(size_t byte, int alignment_rules)
        {
            //位运算效率更高
            return (((byte)+alignment_rules - 1) & ~(alignment_rules - 1));
        }
        //桶号
        static size_t BucketNum(size_t byte, int bucket_shift_rules)
        {
            //位运算效率更高
            return ((byte + (1 << bucket_shift_rules) - 1) >> bucket_shift_rules) - 1;
        }
        //对齐数的修正
        static size_t AlignedNum(size_t byte)
        {
            //我们这里采用这样的对齐规则可以使得整体控制在最多10%左右的内碎片浪费 
            // 数字范围                  对齐规则             对应的桶
            // [1,128]                  8byte对齐           freelist[0,16) 
            // [128+1,1024]             16byte对齐          freelist[16,72) 
            // [1024+1,8*1024]          128byte对齐         freelist[72,128) 
            // [8*1024+1,64*1024]       1024byte对齐        freelist[128,184) 
            // [64*1024+1,256*1024]     8*1024byte对齐      freelist[184,208) 

            if (byte <= 128)
            {
                return AlignedNum(byte, 8);
            }
            else if (byte <= 1024)
            {
                return AlignedNum(byte, 16);

            }
            else if (byte <= 8 * 1024)
            {
                return AlignedNum(byte, 128);

            }
            else if (byte <= 64 * 1024)
            {
                return AlignedNum(byte, 1024);

            }
            else if (byte <= 256 * 1024)
            {
                return AlignedNum(byte, 8 * 1024);
            }
            else
            {
                return AlignedNum(byte, 1<<PAGESIZESHIFT);
            }
        }

        //所在桶的编号
        static size_t BucketNum(size_t byte)
        {
            int bucketarray[] = { 0,16,72,128,184 };

            if (byte <= 128)
            {
                return BucketNum(byte, 3) + bucketarray[0];
            }
            else if (byte <= 1024)
            {
                return BucketNum(byte - 128, 4) + bucketarray[1];

            }
            else if (byte <= 8 * 1024)
            {
                return BucketNum(byte - 1024, 7) + bucketarray[2];
            }
            else if (byte <= 64 * 1024)
            {
                return BucketNum(byte - 8 * 1024, 10) + bucketarray[3];

            }
            else if (byte <= 256 * 1024)
            {
                return BucketNum(byte - 64 * 1024, 13) + bucketarray[4];
            }
            else
            {
                assert(false);
                return -1;
            }
        }
        //申请的内存的个数
        static size_t ObtainedNum(size_t size)
        {
            //为直接从PageCaceh申请计算的
            if (size > MAXMEMORYSIZE)
                return 1;
            //最多给512，最少给两个
            //内存块小就多给点，内存块大就少给点
            size_t retnum = MAXMEMORYSIZE / size;
            if (retnum > 512)
                return 512;
            if (retnum < 2)
                return 2;
            return retnum;
        }
        //申请的页数
        static size_t PageNum(size_t size)
        {
            size_t memorynum = ObtainedNum(size);
            size_t pagenum = ((memorynum * size) >> PAGESIZESHIFT);
            if (!pagenum)  pagenum++;
            return pagenum;
        }
    };
}